package com.king.security.security;

import com.king.security.authentication.TiHomAuthenticationFailureHandler;
import com.king.security.authentication.TiHomAuthenticationSuccessHandler;
import com.king.security.config.SecurityPropertis;
import com.king.security.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import java.util.Arrays;

/**
 * security 核心配置类
 *
 * @author KING
 * @date 2018/8/30 22:25
 */
@Configuration
@ComponentScan("com.king.security")
public class WebSecurityConfig {
    @Autowired
    protected UserRepository userRepository;
    @Autowired
    protected TiHomAuthenticationFailureHandler failureHandler;
    @Autowired
    protected  TiHomAuthenticationSuccessHandler successHandler;
    @Configuration
    @Order(0)
    public class ServiceSecurityConsumerConfigurtion extends WebSecurityConfigurerAdapter {
        @Autowired
        protected SecurityPropertis properties;
        @Autowired
        protected AuthenticationProvider authenticationProvider;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            String[] str1 = {  "/login", "/css/**", "/js/**", "/img/*"};
            String[] str2 = properties.getWeb().getNotAuthMatchers();
            int str1Length = str1.length;
            int str2length = str2.length;

            str1 = Arrays.copyOf(str1, str1Length + str2length);//数组扩容
            System.arraycopy(str2, 0, str1, str1Length, str2length);

            http.csrf().disable()
                    .authorizeRequests()
                    // spring-security 5.0 之后需要过滤静态资源

                    .antMatchers(str1).permitAll()
                    .antMatchers("/user", "/user/**").hasRole("USER")
                    .antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA")
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .loginPage(properties.getWeb().getLoginPath())
                    .loginProcessingUrl(properties.getWeb().getUserLoginPath())
                    .successHandler(getAuthenticationSuccessHandler())
                    .failureHandler(getAuthenticationFailureHandler())
                    .permitAll();


        }

        private AuthenticationFailureHandler getAuthenticationFailureHandler() {
            return failureHandler;
        }

        private AuthenticationSuccessHandler getAuthenticationSuccessHandler() {
            return successHandler;
        }


        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            //指定密码加密所使用的加密器为passwordEncoder()
            //需要将密码加密后写入数据库
            auth.authenticationProvider(authenticationProvider);
        }

    }

    @Bean
    public MyPasswordEncoder myPasswordEncoder() {
        return new MyPasswordEncoder();
    }

    @Bean
    public JwtUserDetailsServiceImpl jwtUserDetailsServiceImpl() {
        JwtUserDetailsServiceImpl jwtUserDetailsService = new JwtUserDetailsServiceImpl();
        jwtUserDetailsService.setUserRepository(userRepository);
        return jwtUserDetailsService;
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        // 创建DaoAuthenticationProvider对象
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        // 不要隐藏"用户未找到"的异常
        provider.setHideUserNotFoundExceptions(false);
        // 通过重写configure方法添加自定义的认证方式。
        provider.setUserDetailsService(jwtUserDetailsServiceImpl());
        // 设置密码加密程序认证
        provider.setPasswordEncoder(myPasswordEncoder());
        return provider;
    }
}
